home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / lib / python2.6 / dist-packages / apport_python_hook.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-10-12  |  9.8 KB  |  319 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. '''Python sys.excepthook hook to generate apport crash dumps.
  5.  
  6. See https://wiki.ubuntu.com/AutomatedProblemReports for details.
  7.  
  8. Copyright (c) 2006 Canonical Ltd.
  9. Authors: Robert Collins <robert@ubuntu.com>
  10.          Martin Pitt <martin.pitt@ubuntu.com>
  11.  
  12. This program is free software; you can redistribute it and/or modify it
  13. under the terms of the GNU General Public License as published by the
  14. Free Software Foundation; either version 2 of the License, or (at your
  15. option) any later version.  See http://www.gnu.org/copyleft/gpl.html for
  16. the full text of the license.
  17. '''
  18. import os
  19. import sys
  20.  
  21. def apport_excepthook(exc_type, exc_obj, exc_tb):
  22.     '''Catch an uncaught exception and make a traceback.'''
  23.     
  24.     try:
  25.         if exc_type in (KeyboardInterrupt,):
  26.             return None
  27.         packaging = impl
  28.         import apport.packaging_impl
  29.         if not packaging.enabled():
  30.             return None
  31.         StringIO = StringIO
  32.         import cStringIO
  33.         import re
  34.         import tempfile
  35.         import traceback
  36.         likely_packaged = likely_packaged
  37.         import apport.fileutils
  38.         
  39.         try:
  40.             binary = os.path.realpath(os.path.join(os.getcwdu(), sys.argv[0]))
  41.         except (TypeError, AttributeError, IndexError):
  42.             packaging.enabled()
  43.             packaging.enabled()
  44.             exc_type in (KeyboardInterrupt,)
  45.             
  46.             try:
  47.                 binary = os.readlink('/proc/%i/exe' % os.getpid())
  48.             except OSError:
  49.                 return None
  50.             
  51.  
  52.             None<EXCEPTION MATCH>OSError
  53.  
  54.         if not os.access(binary, os.X_OK) or not os.path.isfile(binary):
  55.             return None
  56.         if not likely_packaged(binary):
  57.             return None
  58.         import apport.report as apport
  59.         pr = apport.report.Report()
  60.         tb_file = StringIO()
  61.         traceback.print_exception(exc_type, exc_obj, exc_tb, file = tb_file)
  62.         pr['Traceback'] = tb_file.getvalue().strip()
  63.         pr.add_proc_info()
  64.         pr.add_user_info()
  65.         pr['ExecutablePath'] = binary
  66.         pr['PythonArgs'] = '%r' % sys.argv
  67.         if pr.check_ignored():
  68.             return None
  69.         mangled_program = re.sub('/', '_', binary)
  70.         user = os.getuid()
  71.         pr_filename = '/var/crash/%s.%i.crash' % (mangled_program, user)
  72.         if os.path.exists(pr_filename):
  73.             if apport.fileutils.seen_report(pr_filename):
  74.                 os.unlink(pr_filename)
  75.             else:
  76.                 return None
  77.         apport.fileutils.seen_report(pr_filename)
  78.         report_file = os.fdopen(os.open(pr_filename, os.O_WRONLY | os.O_CREAT | os.O_EXCL), 'w')
  79.         os.chmod(pr_filename, 384)
  80.         
  81.         try:
  82.             pr.write(report_file)
  83.         finally:
  84.             report_file.close()
  85.  
  86.     finally:
  87.         if sys:
  88.             sys.__excepthook__(exc_type, exc_obj, exc_tb)
  89.         
  90.  
  91.  
  92.  
  93. def install():
  94.     '''Install the python apport hook.'''
  95.     sys.excepthook = apport_excepthook
  96.  
  97. if __name__ == '__main__':
  98.     import unittest
  99.     import tempfile
  100.     import subprocess
  101.     import os.path as os
  102.     import stat
  103.     import apport.fileutils as apport
  104.     import problem_report
  105.     
  106.     class _PythonHookTest(unittest.TestCase):
  107.         
  108.         def test_env(self):
  109.             '''Check the test environment.'''
  110.             self.assertEqual(apport.fileutils.get_all_reports(), [], 'No crash reports already present')
  111.  
  112.         
  113.         def _test_crash(self, extracode = '', scriptname = None):
  114.             '''Create a test crash.'''
  115.             if scriptname:
  116.                 script = scriptname
  117.                 fd = os.open(scriptname, os.O_CREAT | os.O_WRONLY)
  118.             else:
  119.                 (fd, script) = tempfile.mkstemp(dir = apport.fileutils.report_dir)
  120.             
  121.             try:
  122.                 os.write(fd, "#!/usr/bin/python\ndef func(x):\n    raise Exception, 'This should happen.'\n\n%s\nfunc(42)\n" % extracode)
  123.                 os.close(fd)
  124.                 os.chmod(script, 493)
  125.                 p = subprocess.Popen([
  126.                     script,
  127.                     'testarg1',
  128.                     'testarg2'], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
  129.                 err = p.communicate()[1]
  130.                 self.assertEqual(p.returncode, 1, 'crashing test python program exits with failure code')
  131.                 self.assert_('Exception: This should happen.' in err)
  132.                 self.failIf('OSError' in err, err)
  133.             finally:
  134.                 os.unlink(script)
  135.  
  136.             return script
  137.  
  138.         
  139.         def test_general(self):
  140.             '''general operation of the Python crash hook.'''
  141.             script = self._test_crash()
  142.             reports = apport.fileutils.get_new_reports()
  143.             pr = None
  144.             
  145.             try:
  146.                 self.assertEqual(len(reports), 1, 'crashed Python program produced a report')
  147.                 self.assertEqual(stat.S_IMODE(os.stat(reports[0]).st_mode), 384, 'report has correct permissions')
  148.                 pr = problem_report.ProblemReport()
  149.                 pr.load(open(reports[0]))
  150.             finally:
  151.                 for r in reports:
  152.                     os.unlink(r)
  153.                 
  154.  
  155.             expected_keys = [
  156.                 'InterpreterPath',
  157.                 'PythonArgs',
  158.                 'Traceback',
  159.                 'ProblemType',
  160.                 'ProcEnviron',
  161.                 'ProcStatus',
  162.                 'ProcCmdline',
  163.                 'Date',
  164.                 'ExecutablePath',
  165.                 'ProcMaps',
  166.                 'UserGroups']
  167.             self.assert_(set(expected_keys).issubset(set(pr.keys())), 'report has necessary fields')
  168.             self.assert_('bin/python' in pr['InterpreterPath'])
  169.             self.assertEqual(pr['ExecutablePath'], script)
  170.             self.assertEqual(pr['PythonArgs'], "['%s', 'testarg1', 'testarg2']" % script)
  171.             self.assert_(pr['Traceback'].startswith('Traceback'))
  172.             self.assert_("func\n    raise Exception, 'This should happen." in pr['Traceback'])
  173.  
  174.         
  175.         def test_existing(self):
  176.             '''Python crash hook overwrites seen existing files.'''
  177.             script = self._test_crash()
  178.             to_del = set()
  179.             
  180.             try:
  181.                 reports = apport.fileutils.get_new_reports()
  182.                 to_del.update(reports)
  183.                 self.assertEqual(len(reports), 1, 'crashed Python program produced a report')
  184.                 self.assertEqual(stat.S_IMODE(os.stat(reports[0]).st_mode), 384, 'report has correct permissions')
  185.                 apport.fileutils.mark_report_seen(reports[0])
  186.                 reports = apport.fileutils.get_new_reports()
  187.                 to_del.update(reports)
  188.                 self.assertEqual(len(reports), 0)
  189.                 script = self._test_crash(scriptname = script)
  190.                 reports = apport.fileutils.get_new_reports()
  191.                 to_del.update(reports)
  192.                 self.assertEqual(len(reports), 1)
  193.                 script = self._test_crash(scriptname = script)
  194.                 reports = apport.fileutils.get_new_reports()
  195.                 self.assertEqual(len(reports), 1)
  196.                 to_del.update(reports)
  197.             finally:
  198.                 for r in to_del:
  199.                     os.unlink(r)
  200.                 
  201.  
  202.  
  203.         
  204.         def test_no_argv(self):
  205.             '''with zapped sys.argv.'''
  206.             self._test_crash('import sys\nsys.argv = None')
  207.             reports = apport.fileutils.get_new_reports()
  208.             pr = None
  209.             
  210.             try:
  211.                 self.assertEqual(len(reports), 1, 'crashed Python program produced a report')
  212.                 self.assertEqual(stat.S_IMODE(os.stat(reports[0]).st_mode), 384, 'report has correct permissions')
  213.                 pr = problem_report.ProblemReport()
  214.                 pr.load(open(reports[0]))
  215.             finally:
  216.                 for r in reports:
  217.                     os.unlink(r)
  218.                 
  219.  
  220.             expected_keys = [
  221.                 'InterpreterPath',
  222.                 'Traceback',
  223.                 'ProblemType',
  224.                 'ProcEnviron',
  225.                 'ProcStatus',
  226.                 'ProcCmdline',
  227.                 'Date',
  228.                 'ExecutablePath',
  229.                 'ProcMaps',
  230.                 'UserGroups']
  231.             self.assert_(set(expected_keys).issubset(set(pr.keys())), 'report has necessary fields')
  232.             self.assert_('bin/python' in pr['InterpreterPath'])
  233.             self.assert_(pr['Traceback'].startswith('Traceback'))
  234.  
  235.         
  236.         def _assert_no_reports(self):
  237.             '''Assert that there are no crash reports.'''
  238.             reports = apport.fileutils.get_new_reports()
  239.             
  240.             try:
  241.                 self.assertEqual(len(reports), 0, 'no crash reports present (cwd: %s)' % os.getcwd())
  242.             finally:
  243.                 for r in reports:
  244.                     pass
  245.                 
  246.  
  247.  
  248.         
  249.         def test_interactive(self):
  250.             '''interactive Python sessions never generate a report.'''
  251.             orig_cwd = os.getcwd()
  252.             
  253.             try:
  254.                 for d in ('/tmp', '/usr/local', '/usr'):
  255.                     os.chdir(d)
  256.                     p = subprocess.Popen([
  257.                         'python'], stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
  258.                     (out, err) = p.communicate('raise ValueError')
  259.                     if not p.returncode != 0:
  260.                         raise AssertionError
  261.                     if not out == '':
  262.                         raise AssertionError
  263.                     if not 'ValueError' in err:
  264.                         raise AssertionError
  265.                     self._assert_no_reports()
  266.             finally:
  267.                 os.chdir(orig_cwd)
  268.  
  269.  
  270.         
  271.         def test_ignoring(self):
  272.             '''the Python crash hook respects the ignore list.'''
  273.             (fd, script) = tempfile.mkstemp(dir = apport.fileutils.report_dir)
  274.             ifpath = os.path.expanduser(apport.report._ignore_file)
  275.             orig_ignore_file = None
  276.             
  277.             try:
  278.                 os.write(fd, "#!/usr/bin/python\ndef func(x):\n    raise Exception, 'This should happen.'\n\nfunc(42)\n")
  279.                 os.close(fd)
  280.                 os.chmod(script, 493)
  281.                 if os.path.exists(ifpath):
  282.                     orig_ignore_file = ifpath + '.apporttest'
  283.                     os.rename(ifpath, orig_ignore_file)
  284.                 
  285.                 r = apport.report.Report()
  286.                 r['ExecutablePath'] = script
  287.                 r.mark_ignore()
  288.                 r = None
  289.                 p = subprocess.Popen([
  290.                     script,
  291.                     'testarg1',
  292.                     'testarg2'], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
  293.                 err = p.communicate()[1]
  294.                 self.assertEqual(p.returncode, 1, 'crashing test python program exits with failure code')
  295.                 self.assert_('Exception: This should happen.' in err)
  296.             finally:
  297.                 os.unlink(script)
  298.                 if os.path.exists(ifpath):
  299.                     os.unlink(ifpath)
  300.                 
  301.                 if orig_ignore_file:
  302.                     os.rename(orig_ignore_file, ifpath)
  303.                 
  304.  
  305.             reports = apport.fileutils.get_new_reports()
  306.             pr = None
  307.             
  308.             try:
  309.                 self.assertEqual(len(reports), 0)
  310.             finally:
  311.                 for r in reports:
  312.                     os.unlink(r)
  313.                 
  314.  
  315.  
  316.  
  317.     unittest.main()
  318.  
  319.